package foot.stateless;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;

import foot.modele.Admin;
import foot.modele.Arbitre;
import foot.modele.But;
import foot.modele.Equipe;
import foot.modele.Joueur;
import foot.modele.Match;
import foot.modele.Tournoi;

@Stateless
public class TournoiBeanFacade implements TournoiLocal,TournoiRemote{
	//l'entity manager prévu par persistence.xml
	@PersistenceContext(unitName = "monUnite",type=PersistenceContextType.EXTENDED)
	EntityManager em;
	private boolean genA = false;
	private boolean genE = false;

	@Override
	public Collection<Match> getTouslesMatchs() {
		Collection<Match> collec = em.createQuery("From Match m").getResultList();
		return collec;
	}



	@Override
	public Match getMatchAvecId(int id) {
		return em.find(Match.class, id);
	}


	@Override
	public void ajouterEquipe(Equipe e) {
		em.persist(e);
	}

	@Override
	public Collection<Equipe> getToutesLesEquipes() {
		Collection<Equipe> collec = em.createQuery("From Equipe e").getResultList();
		return collec;
	}

	@Override
	public Equipe getEquipeAvecId(int id) {
		Query q = em.createQuery("From Equipe e where e.id=?1");
		q.setParameter(1, id);
		
		return (Equipe) q.getSingleResult(); 
	}

	@Override
	public void ajouterMatch(Match m) {
		em.persist(m);
	}

	@Override
	public void genererTours() {
		Collection<Equipe> lesEquipes = getToutesLesEquipes();

		if(verifP2(lesEquipes.size())){
			//bon nombre d'équipes
			ArrayList<Equipe> listEquipe  = new ArrayList<Equipe>();
			Iterator<Equipe> it = lesEquipes.iterator();
			while(it.hasNext()){
				listEquipe.add(it.next());
			}
			//on melange les equipes
			Collections.shuffle(listEquipe);
			//attributions du numEquipe
			for(int i = 0; i<listEquipe.size();i++){
				listEquipe.get(i).setNumEquipeTournoi(i);
			}
			//creation des matchs
			//tour de base
			ArrayList<Match> lesMatchs = new ArrayList<Match>();
			int premierMatchAregarder = 0;
			int nb_match = listEquipe.size()/2;
			int nb_match_a_creer = nb_match;
			while(nb_match >1){
				for(int i = 0; i<nb_match;i++){
					if(nb_match == listEquipe.size()/2){
						//tour de base
						Match m = new Match();
						m.setEquipe1(listEquipe.get(2*i));
						m.setEquipe2(listEquipe.get((2*i)+1));
						m.setStatusMatch("non terminé");
						m.setPred1(null);
						m.setPred2(null);
						lesMatchs.add(m);

					}
					else{
						Match m = new Match();
						m.setStatusMatch("non terminé");
						m.setPred1(lesMatchs.get(premierMatchAregarder+2*i));
						m.setPred2(lesMatchs.get(premierMatchAregarder+(2*i)+1));
						lesMatchs.add(m);

					}
				}
				if(nb_match != listEquipe.size()/2){
					premierMatchAregarder += nb_match*2;
				}

				nb_match= nb_match/2;

			}
			if( nb_match_a_creer == 1) {
				Match finale = new Match();
				finale.setEquipe1(listEquipe.get(0));
				finale.setEquipe2(listEquipe.get(1));
				finale.setStatusMatch("non terminé");
				finale.setPred1(null);
				finale.setPred2(null);
				lesMatchs.add(finale);
				Tournoi t = getTournoi();
				t.setRacine(finale);
				t.setEtat(etat.toInt(etat.MATCHGENERE));
			}
			else {
				//il ne reste qu'a créér la finale
				Match finale = new Match();
				finale.setPred1(lesMatchs.get(lesMatchs.size()-2));
				finale.setPred2(lesMatchs.get(lesMatchs.size()-1));
				lesMatchs.add(finale);
				//set le match racine au tournoi
				Tournoi t = getTournoi();
				t.setRacine(finale);
				t.setEtat(etat.toInt(etat.MATCHGENERE));
				//ya plus qu'a persist;				
			}
			for(int i =0;i< lesMatchs.size();i++){
				em.persist(lesMatchs.get(i));
			}
		}

	}

	private Tournoi getTournoi() {
		Tournoi t;
		try {
			t = (Tournoi)em.createQuery("From Tournoi t").getSingleResult();
		}
		catch(NoResultException e) {
			t = createTournoi();
		}
		return t;
	}

	private Tournoi createTournoi() {
		Tournoi t = new Tournoi();
		t.setEtat(etat.toInt(etat.INSCRIPTION));
		em.persist(t);
		return t;
	}

	private boolean verifP2(int size) {
		if(size==0){
			return false;
		}
		if(size == 1){
			return false;
		}
		if(size == 2){
			return true;
		}
		else{
			return verifP2(size/2);
		}
	}

	

	public void peuplerEquipe(){
		//si on a pas deja générer un set d'équipe
		if(!genE){
			Equipe e1;
			for(int z=0;z<8;z++){
				//on va générer 8 équipes
				e1 = new Equipe();
				e1.setNomEquipe("Equipe"+z);
				Joueur j = new Joueur();
				for(int i=0;i<11;i++){
					//on génère 11 joueurs
					j = new Joueur();
					j.setNom(z+"toto"+i);
					j.setPrenom(z+"titi"+i);
					j.setEquipe(e1);
					e1.getLesJoueurs().add(j);
				}
				em.persist(e1);

			}
			genE=true;
		}
	}

	@Override
	public void ajouterArbitre(Arbitre a) {
		em.persist(a);

	}

	@Override
	public Arbitre getArbitreAvecID(int id) {
		return em.find(Arbitre.class, id);
	}

	@Override
	public Collection<Arbitre> getTousLesArbitres() {
		Collection<Arbitre> lesArbitres =em.createQuery("From Arbitre a").getResultList();
		return lesArbitres;
	}

	public void peuplerArbitre() {
		if(!genA){
			Arbitre a;
			for (int i = 0; i< 4;i++){
				a= new Arbitre();
				a.setNomArbitre(i+"ARBit");
				a.setPrenomArbitre(i+"prenomArbitre");

				em.persist(a);

			}
			genA=true;
		}
	}

	@Override
	public void ajouterButAMatch(Match m, Joueur auteur, String heure, boolean tir_au_but) {
		if(!m.isEstTermine()){
			boolean futur = true;
			if(! tir_au_but) {
				int iheure = Integer.parseInt(heure);
				for (But but : m.getLesButs()) {
					if(iheure < Integer.parseInt(but.getHeure())) {
						futur = false;
						break;
					}
				}
			}
			if(futur) {
				But b= new But();
				b.setAuteur(auteur);
				b.setHeure(heure);
				b.setTir_au_but(tir_au_but);
				b.setMatch(m);
				m.getLesButs().add(b);
			}
		}
		else{
			System.err.println("ajout d'un but à un match terminé");
		}
	}

	@Override
	public void affecterArbitreAMatch(Arbitre a, Match m) {
		if(m.getArbitre() == null){
			m.setArbitre(a);
		}

	}

	@Override
	public void inscrireEquipe(String nomEquipe, String [] lesNoms,
			String [] lesPrenoms) {
		Collection<Equipe> lesEquipes = getToutesLesEquipes();
		Iterator<Equipe> it=  lesEquipes.iterator();
		boolean found = false;
		while(!found && it.hasNext()){
			if(it.next().getNomEquipe().equals(nomEquipe)){
				found=true;
			}
		}
		if(!found){
			Equipe e = new Equipe();
			e.setNomEquipe(nomEquipe);
			if( lesNoms.length != lesPrenoms.length){
				System.err.println("pas autant de noms que de prénoms : inscrireEquipe");
			}
			else{
				Joueur j;
				//autant de nom et prenom (c'ets mieux)
				for(int i=0;i<lesNoms.length;i++){

					String name= lesNoms[i];
					String prenom= lesPrenoms[i];
					j=new Joueur();
					j.setEquipe(e);
					j.setNom(name);
					j.setPrenom(prenom);
					e.getLesJoueurs().add(j);
				}
			}
			if(e.getLesJoueurs().size() >= 11)
				em.persist(e);
		}
	}

	@Override
	public void validerMatch(Match m) {
		if(!m.isEstTermine()){
			m.setEstTermine(true);
		}
	}

	@Override
	public Joueur getJoueurWithId(int id) {
		Query q = em.createQuery("From Joueur j where j.idjoueur=?1");
		q.setParameter(1, id);
		return (Joueur) q.getSingleResult();
	}

	@Override
	public void inscrireArbitres(String[] lesNoms, String[] lesPrenoms) {
		if(lesNoms.length == lesPrenoms.length ){
			//si on a le bon nombre de tout
			Arbitre a;
			for(int i=0; i< lesNoms.length;i++){
				if(!lesNoms[i].equals(new String("")) && !(lesNoms[i]==null) && !lesPrenoms[i].equals(new String("")) && !(lesPrenoms[i]==null)){
					a= new Arbitre();
					a.setNomArbitre(lesNoms[i]);
					a.setPrenomArbitre(lesPrenoms[i]);
					em.persist(a);
				}
			}
		}

	}
	@Override
	public Collection<Match> MatchsSansArbitre(){

		Collection<Match> collec =  getTouslesMatchs();
		//		if(collec.isEmpty()){
		//			genererTours();
		//		}
		Query q= em.createQuery("From Match m Where M.arbitre=NULL");
		return q.getResultList();
	}

	@Override
	public void MAJMatch(){
		Collection<Match> lesMatchs = getTouslesMatchs();
		Iterator<Match> it = lesMatchs.iterator();
		while(it.hasNext()){
			Match m = it.next();
			if(m.getEquipe1() == null){
				if(m.getPred1() != null && m.getPred1().isEstTermine()){
					m.setEquipe1(m.getPred1().vainqueur());
				}
			}
			if(m.getEquipe2() == null){
				if(m.getPred2() != null && m.getPred2().isEstTermine()){
					m.setEquipe2(m.getPred2().vainqueur());
				}
			}
		}
	}

	@Override
	public Match getMatchRacine() {
		return getTournoi().getRacine();		
	}


	@Override
	public Collection<Match> getTousLesMatchsEnCours() {
		Query q = em.createQuery("From Match m Where m.estTermine=FALSE and m.equipe1!=NULL and m.equipe2!=NULL");
		return q.getResultList();		
	}

	@Override
	public etat getEtat() {
		return etat.fromInt(getTournoi().getEtat());
	}

	@Override
	public void setEtat(etat e) {
		Tournoi t = getTournoi();
		switch (e) {
		case ENCOURS:
			if(etat.fromInt(t.getEtat()).equals(etat.MATCHGENERE))
				t.setEtat(2);
			break;
		default:
			break;
		}
	}

	@Override
	public boolean getGenA() {
		return genA;
	}

	@Override
	public boolean getGenE() {

		return genE;
	}

	@Override
	public boolean login(String login, String mdp) {
		Admin a;
		try{
			a = (Admin) em.createQuery("From Admin a").getSingleResult();
		}
		catch (NoResultException e) {
			a = createAdmin();
		}
		return (login.equals(a.getLogin()) && mdp.equals(a.getMdp()));
	}
	
	private Admin createAdmin() {
		Admin a = new Admin();
		a.setLogin("admin");
		a.setMdp("admin");
		em.persist(a);
		return a;
	}
}
